#include "kbox.h"

const char *options[] = {"GET", "SET", "DEL", "MOD", "COUNT",
                         "RGET", "RSET", "RDEL", "RMOD", "RCOUNT",
                         "HGET", "HSET", "HDEL", "HMOD", "HCOUNT"};

enum KBoxProtocol
{
    KBoxStart = 0,
    KBoxAGet = KBoxStart,
    KBoxASet,
    KBoxADel,
    KBoxAMod,
    KBoxACount,
    KBoxRGet,
    KBoxRSet,
    KBoxRDel,
    KBoxRMod,
    KBoxRCount,
    KBoxHGet,
    KBoxHSet,
    KBoxHDel,
    KBoxHMod,
    KBoxHCount,
    KBoxCount
};

int KBoxRequest(ConnItem *item)
{
    LOG("KBoxResponse buffer: %s\n", item->rbuffer);

    char *msg = item->rbuffer;
    char *tokens[KBOX_MAX_TOKENS];
    int count = KBoxSplitToken(msg, &tokens);

    for (int i = 0; i < count; i++)
    {
        LOG("%s\n", tokens[i]);
    }

    KBoxParseProtocol(item, tokens, count);
    item->wlen = strlen(item->wbuffer);
    return 0;
}

int KBoxParseProtocol(ConnItem *item, char **tokens, int count)
{
    if (item == NULL || tokens == NULL || count <= 0)
        return -1;

    size_t option = KBoxStart;
    for (; option < KBoxCount; option++)
    {
        if (strcmp(options[option], tokens[0]) == 0)
            break;
    }

    char *msg = item->wbuffer;
    memset(msg, 0, BUFFER_LEN);

    int res = 0;
    switch (option)
    {
    case KBoxAGet:
    {
        LOG("Get\n");
        if (count < 2)
        {
            LOG("Get count error\n");
            return -1;
        }
        char *value = KBoxArrayGet(tokens[1]);
        if (value)
            snprintf(msg, BUFFER_LEN, "%s", value);
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxASet:
    {
        LOG("Set\n");
        if (count != 3)
        {
            LOG("Set count error\n");
            return -1;
        }
        res = KBoxArraySet(tokens[1], tokens[2]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");

        break;
    }
    case KBoxADel:
    {
        LOG("Del\n");
        if (count < 2)
        {
            LOG("Del count error\n");
            return -1;
        }
        res = KBoxArrayDel(tokens[1]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxAMod:
    {
        LOG("Mod\n");
        if (count != 3)
        {
            LOG("Mod count error\n");
            return -1;
        }
        res = KBoxArrayModify(tokens[1], tokens[2]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxACount:
    {
        LOG("ACount\n");
        int count = KBoxArrayCount();
        snprintf(msg, BUFFER_LEN, "%d", count);
        break;
    }
    case KBoxRGet:
    {
        LOG("RGet\n");
        char *value = KBoxRbtreeGet(tokens[1]);
        if (value)
            snprintf(msg, BUFFER_LEN, "%s", value);
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;

        break;
    }
    case KBoxRSet:
    {
        LOG("RSet\n");
        res = KBoxRbtreeSet(tokens[1], tokens[2]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxRDel:
    {
        LOG("RDel\n");
        res = KBoxRbtreeDelete(tokens[1]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxRMod:
    {
        LOG("RMod\n");
        res = KBoxRbtreeModify(tokens[1], tokens[2]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxRCount:
    {
        LOG("RCount\n");
        snprintf(msg, BUFFER_LEN, "%d", KBoxRbtreeCount());
        break;
    }
    case KBoxHGet:
    {
        LOG("HGet\n");
        char *value = KBoxHashGet(tokens[1]);
        if (value)
            snprintf(msg, BUFFER_LEN, "%s", value);
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxHSet:
    {
        LOG("HSet\n");
        res = KBoxHashSet(tokens[1], tokens[2]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxHDel:
    {
        LOG("HDel\n");
        res = KBoxHashDelete(tokens[1]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxHMod:
    {
        LOG("HMod\n");
        res = KBoxHashModify(tokens[1], tokens[2]);
        if (!res)
            snprintf(msg, BUFFER_LEN, "Success");
        else
            snprintf(msg, BUFFER_LEN, "Failed");
        break;
    }
    case KBoxHCount:
    {
        LOG("HCount\n");
        snprintf(msg, BUFFER_LEN, "%d", KBoxHashCount());
        break;
    }
    default:
        item->wlen = snprintf(item->wbuffer, BUFFER_LEN, "option error");
        break;
    }
}

int KBoxResponse()
{
    return 0;
}

void DestoryDataStructures()
{
    LOG("DestoryDataStructures\n");
#if ENABLE_ARRAY_KBOX == 1
    KBoxArrayDestory();
#endif
#if ENABLE_RBTREE_KBOX == 1
    KBoxRbtreeDestory();
#endif
#if ENABLE_HASH_KBOX == 1
    KBoxHashDestory();
#endif
    exit(0);
}

int InitDataStructures()
{
#if ENABLE_ARRAY_KBOX == 1
    KBoxArrayCreate();
#endif
#if ENABLE_RBTREE_KBOX == 1
    KBoxRbtreeCreate();
#endif
#if ENABLE_HASH_KBOX == 1
    KBoxHashCreate();
#endif
}

int main()
{
    InitDataStructures();
    signal(SIGINT, DestoryDataStructures);
    signal(SIGTERM, DestoryDataStructures);
#if ENABLE_NETWORK_SELECT == NETWORK_EPOLL
    EpollEntry();
#elif ENABLE_NETWORK_SELECT == NETWORK_NOYCO
    NtyEntry();
#endif
}

#if split == 0
int KBoxSplitToken(char *msg, char **tokens)
{
    if (msg == NULL || tokens == NULL)
    {
        return -1;
    }

    char *token = strtok(msg, " ");
    int index = 0;
    while (token != NULL)
    {
        tokens[index++] = token;
        token = strtok(NULL, " ");
    }
    return index;
}
#endif